終於進到 R-type 指令了!
指令實作已經有固定流程了,很單純,
另外花了一點時間修改昨天的 Exception。
指令格式如下:
|31 25|24 20|19 15|14 12|11 7|6 0|
+---------------------------------------------------+
| func7 | rs2 | rs1 | funct3 | rd | opcode |
+---------------------------------------------------+
rd = rs1 + rs2
|31 25|24 20|19 15|14 12|11 7|6 0|
+-------------------------------------------------------+
| 0000000 | rs2 | rs1 | 000 | rd | 0110011 |
+-------------------------------------------------------+
rd = rs1 - rs2
|31 25|24 20|19 15|14 12|11 7|6 0|
+-------------------------------------------------------+
| 0100000 | rs2 | rs1 | 000 | rd | 0110011 |
+-------------------------------------------------------+
github 頁面 Tag: ITDay22
蘭尼斯特猴來還債了!
昨天只是簡單的在 ECALL
和 EBREAK
的時候結束模擬,
相信也有讀者注意到 LOAD/STORE、JUMP/BRANCH Exception 都沒有處理,
沒做的原因是因為當時還要處理 Memory 和 Program Counter 設計的問題,
必須讓自己專注在當下最重要的事情上,於是把 Exception 相關的議題延後處理。
Exception Handling 並不屬於 Executor 的功能,
這次先轉交給 CPU,為之後的 Exception/Interrupt 實作做一點準備,
Cause 先簡單處理,之後再補上各個 Exception 的編號。
//executor.cpp
...
void EXECUTOR::ECALL_E()
{
const int cause = 11;
cpu->raise_exception(cause);
}
void EXECUTOR::EBREAK_E()
{
const int cause = 3;
cpu->raise_exception(cause);
}
...
指令部分相對單純,
這次一樣用 ADD 當範例,實作如下:
//executor.cpp
...
void EXECUTOR::reg_dispatch()
{
switch (instruction_decoder->get_func3()) {
case INSTRUCTION_DECODER_INTERFACE::ADDI_FN3: //SUB_FN3 is the same
switch (instruction_decoder->get_func7()) {
case INSTRUCTION_DECODER_INTERFACE::ADD_FN7:
ADD_E();
break;
...
void EXECUTOR::ADD_E()
{
auto rd = instruction_decoder->get_rd();
auto rs1 = instruction_decoder->get_rs1();
auto rs2 = instruction_decoder->get_rs2();
auto value = register_file->get_value_integer(rs1) + register_file->get_value_integer(rs2);
register_file->set_value_integer(rd, value);
}
...
//instructionDecoderInterface.h
...
REG_OP = 0b0110011,
...
ADD_FN3 = 0b000,
...
ADD_FN7 = 0b0000000,
...